#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#include "lrtsp_stream.h"
#include "lrtsp_typedef.h"
#include "rtsp_client.h"
#include "rtp.h"


typedef enum _LrsStatus
{
    STATUS_NOT_START,
    STATUS_RUNNING,
    STATUS_END,
}LrsStatus;


#define MAX_STREAM_RTSPCLIENT_NUMS 10

struct LrtspStreamGroup{
    struct LrtspStream* stream;
    LrsStatus status;
    int nr;
    int max_nr;   
    pthread_t pthread_pid;
    struct RtspClient* rtsp_client[1];
};

#define MAX_LRTSP_STREAM_GROUP_NUMS 10

struct lrs_manager{
    int nr;
    int max_nr;
	struct LrtspStreamGroup* group[1];
};

static struct lrs_manager* L = NULL;

int lrtsp_stream_manager_init(void)
{
    int max_nr = 4;

    if(L == NULL){
        L = (struct lrs_manager*)malloc(sizeof(struct lrs_manager) + sizeof(struct LrtspStreamGroup*)*(max_nr + 1));
        if(L == NULL){
            printf("malloc memory failed!\n");
            return -1;
        }
        L->nr = 0;
        L->max_nr = 0;
    }

    return 0;
}


void lrtsp_stream_manager_deinit(void)
{
    int i = 0;
    struct LrtspStreamGroup* group = NULL;

    if(L){
        for(i = 0; i < L->nr; i++){
            group = L->group[i];
            free(group);
        }
        free(L);
        L = NULL;
    }
    
    return ;
}

int lrtsp_stream_manager_add_stream(struct LrtspStream* stream)
{
    return_val_if_fail(stream != NULL, -1);

    int i  = 0;
    int is_find = 0;
    
    for(i = 0; i < L->nr; i++){
        if(strcmp(L->group[i]->stream->rtsp_filename, stream->rtsp_filename) == 0){
            is_find = 1;
            break;
        }
    }
    if(is_find){
        return -1;
    }
   
    struct LrtspStreamGroup* group = NULL;
    group = (struct LrtspStreamGroup*)malloc(sizeof(struct LrtspStreamGroup) + sizeof(struct RtspClient*)*(MAX_STREAM_RTSPCLIENT_NUMS + 1));
    group->status = STATUS_NOT_START;
    group->max_nr = MAX_STREAM_RTSPCLIENT_NUMS;
    group->nr = 0;
    group->stream = stream;
    
	L->group[L->nr++] = group;

    return 0;
}

void* _stream_rtp_thread(void* para)
{
    struct LrtspStreamGroup* group = NULL;
    struct LrtspStream* stream;
    void* stream_data = NULL;
    int len = 0;
    int i = 0;
    struct RtspClient* rtsp_client = NULL;
    struct LRSDataHeader header;
    int ret = -1;

    group  = (struct LrtspStreamGroup*)para;
    stream = group->stream;
   
    for(;;){
        ret = stream->pull_stream_data(stream, &stream_data, &len, &header);
        if(ret != 0 || stream_data == NULL || len == 0){   
            usleep(1000);
            continue;
        }
        for(i = 0; i < group->nr; i++){
            rtsp_client = group->rtsp_client[i];
            rtsp_client_set_timestamp(rtsp_client, header.pts);
            ret = rtp_send_data(rtsp_client, stream_data, len, header);
            if(ret < 0){
                break;
            }
        }
    }
    
    return NULL;
}

int lrtsp_stream_add_rtsp_client(struct RtspClient* rtsp_client)
{
    return_val_if_fail(rtsp_client != NULL, -1);

    int i  = 0;
    int is_find = 0;
    struct LrtspStreamGroup* group = NULL;
    int ret  = 0;


    for(i = 0; i < L->nr; i++){
        if(strcmp(L->group[i]->stream->rtsp_filename, rtsp_client_get_filename(rtsp_client)) == 0){
            group = L->group[i];
            is_find = 1;
            break;
        }
    }
    if(!is_find){
        printf("Error:not find the stream for the rtsp client rtsp filename(%s)\n", rtsp_client_get_filename(rtsp_client));
        return -1;
    }

    /*add rtsp client to */
    if(group->nr == group->max_nr){
        printf("Debug:the lrtsp stream group rtsp cliend is over!\n");
        return -1;
    }
    
    group->rtsp_client[group->nr++] = rtsp_client;
    
    if(group->status != STATUS_RUNNING){
        /*create a thread*/
        ret = pthread_create(&group->pthread_pid, 0, _stream_rtp_thread, (void*)group);
    }

    return ret;    
}

static int _group_remove_rtsp_client(struct LrtspStreamGroup* group, struct RtspClient* rtsp_client)
{
    int i  = 0;
    
	for(i = 0; i < group->nr; i++){
		if(group->rtsp_client[i] == rtsp_client){
			break;
		}
	}
	if(i < group->nr){
		for(;(i+1)< group->nr;i++){
			group->rtsp_client[i] = group->rtsp_client[i+1];
		}
		group->nr--;
		group->rtsp_client[group->nr] = NULL;
	}

	return 0;
}

int lrtsp_stream_remove_rtsp_client(struct RtspClient* rtsp_client)
{
    return_val_if_fail(rtsp_client != NULL, -1);
    
    int i  = 0;
    int is_find = 0;
    struct LrtspStreamGroup* group = NULL;
    
    for(i = 0; i < L->nr; i++){
        if(strcmp(L->group[i]->stream->rtsp_filename, rtsp_client_get_filename(rtsp_client)) == 0){
            group = L->group[i];
            is_find = 1;
            break;
        }
    }

    if(!is_find){
        printf("lrtsp_stream_remove_rtsp_client:Error:not find the stream for the rtsp client rtsp filename(%s)\n", rtsp_client_get_filename(rtsp_client));
        return -1;
    }
    
    _group_remove_rtsp_client(group,  rtsp_client);

    return 0;
}

